/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package genomemap.cef.pui;

import cef.event.Event;
import cef.event.TestModelIDEvent;
import cef.pui.EventConstructionException;
import cef.pui.EventImpl;
import cef.pui.pob.Builder;
import cef.pui.pob.BuilderException;
import commons.core.Generator;
import commons.core.LikelihoodComputer;
import commons.core.MultiLHoodComputer;
import commons.core.Simulator;
import commons.util.ListUtil;
import commons.util.base.Converter;
import genomemap.data.KSA00Data;
import genomemap.model.KSA00;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import static cef.pui.pob.Builders.of_Integer;
import static genomemap.cef.pui.pob.Builders_Gen.*;

/**
 * Implements {@code TestModelIDEvent} using the following properties.
 * <ul>
 *     <li>
 *         {@code genomemap.builder.KSA00.delegate = fully qualified builder class name for the same value type} <br/>OR<br/>
 *         {@code genomemap.builder.KSA00Data.url = ksa00data:xml//URL }<a href="genomemap/cef/pui/pob/doc-files/KSA00-data.xml.txt">file format</a>, must accompany the <a href="genomemap/cef/pui/pob/doc-files/KSA00Data.xsd.txt">schema</a>
 *     </li>
 *     <li>{@code genomemap.builder.KSA00Lhood.implCode = KSA00:rla | KSA00:sfa}</li>
 * </ul>
 *
 * @version 1.3.0
 * @author Susanta Tewari
 * @history Created on 2/1/13
 * @since 1.3.0
 */
public class TestKSA00ModelIDEventImpl extends EventImpl
        implements TestModelIDEvent<KSA00, KSA00Data> {

    /** model builder */
    private final Builder<KSA00> m_b;

    /** sample size builder */
    private final Builder<Integer> sample_size_b;

    /** model count builder */
    private final Builder<Integer> model_count_b;

    /** model generator builder */
    private final Builder<Generator.MODEL<KSA00, KSA00>> mg_b;

    /** data simulator builder */
    private final Builder<Simulator.DATA<KSA00, KSA00Data>> ds_b;

    /** LikelihoodComputer builder for KSA00Data */
    private final Builder<LikelihoodComputer<KSA00Data>> lc_b;

    public TestKSA00ModelIDEventImpl(final Properties props) throws EventConstructionException {

        super(props);

        super.processEventProperties(getImplementedEventInterfaces());


        // builder: model
        m_b = Builder.of_delegate(of_Data_KSA00_File(props, null),
                                  new Converter<KSA00Data, KSA00>() {

            @Override
            public KSA00 convert(KSA00Data input) {
                return input.getModel();
            }

        });


        // builder: sample size, modelCount
        sample_size_b = of_Integer(props, "sampleSize", "genomemap.builder");
        model_count_b = of_Integer(props, "modelCount", "genomemap.builder");


        // builders: other
        mg_b = of_Generator_Model_KSA00(props, null);
        ds_b = of_Simulator_Data_KSA00(props, null);
        lc_b = of_LHoodComputer_KSA00(props, null);
    }

    @Override
    public KSA00 getInputModel() {
        return m_b.build();
    }

    @Override
    public int getModelCount() {
        return model_count_b.canBuild() ? model_count_b.build() : 50;
    }

    @Override
    public String getModelDescription(final KSA00 m) {
        return m.getProbes().toString();
    }

    @Override
    public BigDecimal getModelDistance(final KSA00 m1, final KSA00 m2) {
        return new BigDecimal(ListUtil.countDiff(m1.getProbes(), m2.getProbes()));
    }

    @Override
    public int getSampleSize() {
        return sample_size_b.canBuild() ? sample_size_b.build() : 20;
    }

    @Override
    protected List<Class<? extends Event>> getImplementedEventInterfaces() {

        final List<Class<? extends cef.event.Event>> result = new ArrayList<>(2);

        result.add(TestModelIDEvent.class);
        result.add(Event.class);

        return result;
    }

    @Override
    public Generator.MODEL<KSA00, KSA00> getModelGenerator() throws BuilderException {
        return mg_b.build();
    }

    @Override
    public Simulator.DATA<KSA00, KSA00Data> getDataSimulator() throws BuilderException {
        return ds_b.build();
    }

    /**
     * @return Provides a serial implementation as described in {@link commons.core.MultiLHoodComputer.ofDefault()}.
     */
    @Override
    public MultiLHoodComputer<KSA00, KSA00Data, KSA00Data> getMultiLHoodComputer() {
        return MultiLHoodComputer.ofDefault(lc_b.build());
    }
}
